package com.sunlee.common.service.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.sunlee.common.core.constant.Constant;
import com.sunlee.common.core.entity.PageData;
import com.sunlee.common.core.enums.ErrorCodeEnum;
import com.sunlee.common.core.exception.BusinessException;
import com.sunlee.common.core.utils.ListPageUtil;
import com.sunlee.common.service.dao.UserActionDao;
import com.sunlee.common.service.dto.*;
import com.sunlee.common.service.dto.req.UserActionDetailReqDTO;
import com.sunlee.common.service.entity.ProductEntity;
import com.sunlee.common.service.entity.UserActionEntity;
import com.sunlee.common.service.enums.ActionTypeEnum;
import com.sunlee.common.service.enums.StatusEnum;
import com.sunlee.common.service.po.ProductActionPO;
import com.sunlee.common.service.service.ProductService;
import com.sunlee.common.service.service.UserActionService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 用户行为表
 *
 * @author sunlee
 */
@Service
public class UserActionServiceImpl extends CrudServiceImpl<UserActionDao, UserActionEntity, UserActionDTO> implements UserActionService {

    @Autowired
    @Lazy
    private ProductService productService;

    @Override
    public int userRecordById(Long uId, Long pId, int actionType) {
        return baseMapper.countUserRecordById(uId, pId, actionType);
    }

    @Override
    public String downloadById(Long userId, Long pId) {

        // 查询该商品的下载地址
        ProductDTO productDTO = productService.getOwn(pId);

        // 校验商品状态
        if (Objects.isNull(productDTO) || productDTO.getStatus() == StatusEnum.INVALID.getCode()) {
            throw new BusinessException(ErrorCodeEnum.RESOURCES_REMOVED);
        }

        // 校验下载地址
        String downloadUrl = productDTO.getDownloadUrl();
        if (StringUtils.isBlank(downloadUrl) || !downloadUrl.startsWith(Constant.HTTP)) {
            throw new BusinessException(ErrorCodeEnum.RESOURCE_NOT_FOUND);
        }

        // 校验用户是否下载过
        UserActionEntity entity = getUserRecord(userId, pId, ActionTypeEnum.DOWNLOAD.getCode());

        if (Objects.isNull(entity)) {
            entity = UserActionEntity.builder()
                    .userId(userId)
                    .productId(pId)
                    .actionType(ActionTypeEnum.DOWNLOAD.getCode())
                    .createDate(new Date())
                    .build();
        }
        entity.setStatus(StatusEnum.VALID.getCode());
        entity.setUpdateDate(new Date());
        saveOrUpdate(entity);

        return downloadUrl;
    }

    @Override
    public Boolean collectionById(Long userId, Long pId, Integer status) {

        // 当进行收藏时，才校验商品状态；取消收藏不校验，允许用户删除记录
        if (status == StatusEnum.VALID.getCode()) {
            ProductDTO productDTO = productService.getOwn(pId);
            if (Objects.isNull(productDTO) || productDTO.getStatus() == StatusEnum.INVALID.getCode()) {
                throw new BusinessException(ErrorCodeEnum.RESOURCES_REMOVED);
            }
        }

        UserActionEntity entity = getUserRecord(userId, pId, ActionTypeEnum.COLLECTION.getCode());
        if (Objects.isNull(entity)) {
            entity = UserActionEntity.builder()
                    .userId(userId)
                    .productId(pId)
                    .actionType(ActionTypeEnum.COLLECTION.getCode())
                    .createDate(new Date())
                    .build();
        }

        entity.setStatus(status);
        entity.setUpdateDate(new Date());

        return saveOrUpdate(entity);
    }

    @Override
    public Boolean previewById(Long userId, Long pId) {
        try {
            UserActionEntity entity = getUserRecord(userId, pId, ActionTypeEnum.PREVIEW.getCode());
            if (Objects.isNull(entity)) {
                entity = UserActionEntity.builder()
                        .userId(userId)
                        .productId(pId)
                        .actionType(ActionTypeEnum.PREVIEW.getCode())
                        .createDate(new Date())
                        .build();
            }
            entity.setStatus(StatusEnum.VALID.getCode());
            entity.setUpdateDate(new Date());
            return saveOrUpdate(entity);
        } catch (Exception e) {
            log.error("[商品浏览]埋点异常", e);
        }
        return false;
    }

    @Override
    public UserActionCountDTO countByUserId(Long userId) {
        List<UserActionEntity> userActionEntities = listByUserIdAndType(userId, null);

        if (CollectionUtils.isEmpty(userActionEntities)) {
            return UserActionCountDTO.builder()
                    .collectionNum(0)
                    .downloadNum(0)
                    .previewNum(0)
                    .build();
        }
        Map<Integer, List<UserActionEntity>> map = userActionEntities.stream()
                .collect(Collectors.groupingBy(UserActionEntity::getActionType));

        List<Long> downloadIds = Optional.ofNullable(map.get(ActionTypeEnum.DOWNLOAD.getCode()))
                .orElse(Collections.emptyList())
                .stream()
                .map(UserActionEntity::getProductId)
                .collect(Collectors.toList());

        List<Long> collectionIds = Optional.ofNullable(map.get(ActionTypeEnum.COLLECTION.getCode()))
                .orElse(Collections.emptyList())
                .stream()
                .map(UserActionEntity::getProductId)
                .collect(Collectors.toList());

        int previewNum = Optional.ofNullable(map.get(ActionTypeEnum.PREVIEW.getCode())).orElse(Collections.emptyList()).size();

        return UserActionCountDTO.builder()
                .collectionIds(collectionIds)
                .downloadIds(downloadIds)
                .collectionNum(collectionIds.size())
                .downloadNum(downloadIds.size())
                .previewNum(previewNum)
                .build();
    }

    @Override
    public PageData<UserActionDetailDTO> listByType(Long userId, UserActionDetailReqDTO dto) {

        // 查询用户行为总数
        List<UserActionEntity> totalList = listByUserIdAndType(userId, dto.getType());

        if (CollectionUtils.isEmpty(totalList)) {
            return new PageData<>(Collections.emptyList(), 0);
        }

        if (!Objects.isNull(dto.getLimit()) && dto.getLimit() > 0) {
            // 分页切割用户行为总数
            ListPageUtil<UserActionEntity> pageList = new ListPageUtil<>(totalList, dto.getPage(), dto.getLimit());
            if (CollectionUtils.isEmpty(pageList.getData())) {
                return new PageData<>(Collections.emptyList(), totalList.size());
            }
            totalList = pageList.getData();

        }

        List<Long> pIds = totalList.stream().map(UserActionEntity::getProductId).collect(Collectors.toList());

        Map<Long, List<UserActionEntity>> pageMap = totalList.stream().collect(Collectors.groupingBy(UserActionEntity::getProductId));

        // 根据商品Id查询详情
        List<ProductEntity> productEntities = productService.selectList(new LambdaQueryWrapper<ProductEntity>()
                .in(ProductEntity::getId, pIds));

        // 封装返回的数据
        List<UserActionDetailDTO> collect = productEntities.stream()
                .map(item -> {
                    List<UserActionEntity> itemMap = pageMap.get(item.getId());
                    return UserActionDetailDTO.builder()
                            .productId(item.getId())
                            .icon(item.getIcon())
                            .name(item.getName())
                            .tag(item.getTag())
                            .shortDesc(item.getShortDesc())
                            .title(item.getTitle())
                            .id(itemMap.get(0).getId())
                            .actionType(itemMap.get(0).getActionType())
                            .updateDate(itemMap.get(0).getUpdateDate())
                            .createDate(itemMap.get(0).getCreateDate())
                            .build();
                })
                .sorted(Comparator.comparing(UserActionDetailDTO::getUpdateDate).reversed())
                .collect(Collectors.toList());

        return new PageData<>(collect, totalList.size());
    }


    public List<UserActionEntity> listByUserIdAndType(Long uId, Integer type) {
        return list(new LambdaQueryWrapper<UserActionEntity>()
//                .select(UserActionEntity::getProductId, UserActionEntity::getActionType, UserActionEntity::getUpdateDate, UserActionEntity::getCreateDate)
                        .eq(UserActionEntity::getUserId, uId)
                        .eq(UserActionEntity::getStatus, StatusEnum.VALID.getCode())
                        .eq(Objects.nonNull(type), UserActionEntity::getActionType, type)
                        .orderByDesc(UserActionEntity::getUpdateDate)
        );
    }

    /**
     * 根据条件查询某条记录
     *
     * @param uId  用户ID
     * @param pId  商品ID
     * @param type 用户行为类型
     * @return 实体UserActionEntity
     */
    private UserActionEntity getUserRecord(Long uId, Long pId, int type) {
        return baseMapper.getUserRecord(uId, pId, type);
    }

    /**
     * 根据商品集合ID，查询商品对应的下载数、浏览数、收藏数
     *
     * @param pIds 商品集合
     * @return 统计数
     */
    @Override
    public Map<Long, ProductActionDTO> getProductActionDataByIds(List<Long> pIds) {
        List<ProductActionPO> list = baseMapper.countByProductId(pIds);

        if (CollectionUtils.isEmpty(list)) {
            return Collections.emptyMap();
        }

        Map<Long, ProductActionDTO> result = new HashMap<>(list.size());

        list.forEach(item -> {
            ProductActionDTO dto = result.get(item.getProductId());
            if (Objects.isNull(dto)) {
                dto = new ProductActionDTO();
                result.put(item.getProductId(), dto);
            }
            if (ActionTypeEnum.DOWNLOAD.getCode() == item.getActionType()) {
                dto.setDownloadNum(item.getCount());
            } else if (ActionTypeEnum.PREVIEW.getCode() == item.getActionType()) {
                dto.setPreviewNum(item.getCount());
            } else if (ActionTypeEnum.COLLECTION.getCode() == item.getActionType()) {
                dto.setCollectionNum(item.getCount());
            }
        });

        return result;
    }

    @Override
    public Boolean updateByIdAndUserId(Long id, Long uId, Long status) {
        return update(new LambdaUpdateWrapper<UserActionEntity>()
                .eq(UserActionEntity::getId, id)
                .eq(UserActionEntity::getUserId, uId)
                .set(UserActionEntity::getStatus, status));
    }
}




